package com.llu.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.llu.entity.Book;
import com.llu.entity.Borrow;
import com.llu.entity.User;
import com.llu.entity.UserBorrowView;
import com.llu.feign.BookFeignClient;
import com.llu.feign.UserFeignClient;
import com.llu.mapper.BorrowDao;
import com.llu.service.BorrowService;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (Borrow)表服务实现类
 *
 * @author makejava
 * @since 2024-08-23 10:51:10
 */
@Service("borrowService")
public class BorrowServiceImpl implements BorrowService {
    @Resource
    private BorrowDao borrowDao;
    @Resource
    // RestTemplate 支持多种方式的远程调用
    private RestTemplate template;

    @Resource
    UserFeignClient userClient;
    @Resource
    BookFeignClient bookClient;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Borrow queryById(String id) {
        return this.borrowDao.queryById(id);
    }


    /**
     * 分页查询
     *
     * @param borrow 筛选条件
     * @param pageRequest      分页对象
     * @return 查询结果
     */
    @Override
    public Page<Borrow> queryByPage(Borrow borrow, PageRequest pageRequest) {
        long total = this.borrowDao.count(borrow);
        return new PageImpl<>(this.borrowDao.queryAllByLimit(borrow), pageRequest, total);
    }

    /**
     * 新增数据
     *
     * @param borrow 实例对象
     * @return 实例对象
     */
    @Override
    public Borrow insert(Borrow borrow) {
        this.borrowDao.insert(borrow);
        return borrow;
    }

    /**
     * 修改数据
     *
     * @param borrow 实例对象
     * @return 实例对象
     */
    @Override
    public Borrow update(Borrow borrow) {
        this.borrowDao.update(borrow);
        return this.queryById(borrow.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.borrowDao.deleteById(id) > 0;
    }


    @Override
    @SentinelResource("getBook")
    @SneakyThrows
    public UserBorrowView queryByUid(String uid) {
        // ====== 使用cloud 的远程调用
        // 现在拿到借阅关联信息了，怎么调用其他服务获取信息呢？
//        Borrow borrow = new Borrow();
//        borrow.setUid(uid);
//        List<Borrow> borrowList = borrowDao.queryAllByLimit(borrow);
//        // 这里不用再写IP，直接写服务名称 userservice
//        User user = this.template.getForObject("http://userservice/user/"+uid, User.class);
//        // 这里通过调用 getForObject 来请求其他服务，并将结果自动进行封装
//        List<Book> bookList = borrowList
//                .stream()
//                .map(b -> this.template.getForObject("http://bookservice/book/"+b.getBid(), Book.class))
//                .collect(Collectors.toList());
//        return new UserBorrowView(user, bookList);
        // ====== 使用cloud 的远程调用

        // 使用Alibaba的远程调用
        Borrow borrow = new Borrow();
        borrow.setUid(uid);
        List<Borrow> borrows = borrowDao.queryAllByLimit(borrow);
        User user = userClient.getUserById(Integer.parseInt(uid));
        List<Book> bookList = borrows
                .stream()
                .map(b -> bookClient.getBookById(Integer.parseInt(b.getBid())))
                .collect(Collectors.toList());
        return new UserBorrowView(user, bookList);
    }

    @Override
    public Boolean doBorrow(int uid, int bid) {
        //1. 判断图书和用户是否都支持借阅
        if(bookClient.bookRemain(bid) < 1)
            throw new RuntimeException("图书数量不足");
        if(userClient.userRemain(uid) < 1)
            throw new RuntimeException("用户借阅量不足");
        //2. 首先将图书的数量-1
        if(!bookClient.bookBorrow(bid))
            throw new RuntimeException("在借阅图书时出现错误！");
        //3. 添加借阅信息
        if(this.borrowDao.getBorrow(uid, bid) != null)
            throw new RuntimeException("此书籍已经被此用户借阅了！");
        if(this.borrowDao.addBorrow(uid, bid) <= 0)
            throw new RuntimeException("在录入借阅信息时出现错误！");
        //4. 用户可借阅-1
        if(!userClient.userBorrow(uid))
            throw new RuntimeException("在借阅时出现错误！");
        //完成
        return true;

    }
}
